"""用户水平追踪服务"""
from typing import Dict, Any, Optional
from datetime import datetime, timedelta
from app.core.database import RedisClient
from app.services.difficulty_service import difficulty_service
import json


class UserLevelService:
    """用户水平追踪服务"""
    
    def __init__(self):
        try:
            self.redis = RedisClient.get_client()
            self.redis.ping()
        except Exception as e:
            print(f"警告: Redis连接失败，将使用内存存储: {e}")
            self.redis = None
            self._memory_storage = {}
    
    def get_user_level(self, user_id: str) -> Dict[str, Any]:
        """
        获取用户当前水平
        
        Returns:
            {
                "current_difficulty": str,  # 当前适合的难度级别
                "accuracy_by_difficulty": Dict[str, float],  # 各难度级别的准确率
                "can_advance": bool,  # 是否可以进阶
                "recommended_difficulty": str  # 推荐的难度级别
            }
        """
        # 获取各难度级别的准确率
        accuracy_by_difficulty = self._get_accuracy_by_difficulty(user_id)
        
        # 确定当前适合的难度级别
        current_difficulty = self._determine_current_difficulty(accuracy_by_difficulty)
        
        # 判断是否可以进阶
        can_advance = self._can_advance(accuracy_by_difficulty, current_difficulty)
        
        # 推荐难度级别
        recommended_difficulty = self._get_recommended_difficulty(
            current_difficulty, can_advance, accuracy_by_difficulty
        )
        
        return {
            "user_id": user_id,
            "current_difficulty": current_difficulty,
            "accuracy_by_difficulty": accuracy_by_difficulty,
            "can_advance": can_advance,
            "recommended_difficulty": recommended_difficulty,
            "updated_at": datetime.now().isoformat()
        }
    
    def _get_accuracy_by_difficulty(self, user_id: str) -> Dict[str, float]:
        """获取用户在各难度级别的准确率"""
        difficulties = ["easy", "medium", "hard"]
        accuracy_by_difficulty = {}
        
        # 获取最近30天的答题记录
        end_date = datetime.now()
        start_date = end_date - timedelta(days=30)
        
        for difficulty in difficulties:
            total = 0
            correct = 0
            
            current_date = start_date
            while current_date <= end_date:
                date_str = current_date.strftime("%Y-%m-%d")
                records = self._get_daily_records(user_id, date_str)
                
                for record in records:
                    question_id = record.get("question_id")
                    if question_id:
                        question_difficulty = difficulty_service.get_difficulty_level(question_id)
                        if question_difficulty == difficulty:
                            total += 1
                            if record.get("is_correct", False):
                                correct += 1
                
                current_date += timedelta(days=1)
            
            accuracy = (correct / total * 100) if total > 0 else 0.0
            accuracy_by_difficulty[difficulty] = round(accuracy, 1)
        
        return accuracy_by_difficulty
    
    def _get_daily_records(self, user_id: str, date: str) -> list:
        """获取指定日期的答题记录"""
        records = []
        
        if self.redis:
            try:
                record_key = f"daily_record:{user_id}:{date}"
                if self.redis.exists(record_key):
                    record_data = self.redis.hgetall(record_key)
                    for qid, record_str in record_data.items():
                        try:
                            if isinstance(record_str, bytes):
                                record_str = record_str.decode('utf-8')
                            record = json.loads(record_str) if isinstance(record_str, str) else record_str
                            record["question_id"] = qid.decode('utf-8') if isinstance(qid, bytes) else qid
                            records.append(record)
                        except:
                            pass
            except Exception as e:
                print(f"获取答题记录失败: {e}")
        
        # 从内存存储获取
        if not records:
            try:
                from app.services.daily_learning_service import daily_learning_service
                from app.services.training_service import training_service
                
                memory_key = f"{user_id}:{date}"
                for service in [daily_learning_service, training_service]:
                    if hasattr(service, '_daily_records') and memory_key in service._daily_records:
                        for qid, record in service._daily_records[memory_key].items():
                            record["question_id"] = qid
                            records.append(record)
            except:
                pass
        
        return records
    
    def _determine_current_difficulty(self, accuracy_by_difficulty: Dict[str, float]) -> str:
        """确定用户当前适合的难度级别"""
        # 如果easy级别准确率>80%，可以尝试medium
        if accuracy_by_difficulty.get("easy", 0) >= 80:
            # 如果medium级别也有一定准确率，可以尝试hard
            if accuracy_by_difficulty.get("medium", 0) >= 80:
                return "hard"
            return "medium"
        return "easy"
    
    def _can_advance(self, accuracy_by_difficulty: Dict[str, float], current_difficulty: str) -> bool:
        """判断是否可以进阶（准确率>80%）"""
        if current_difficulty == "easy":
            return accuracy_by_difficulty.get("easy", 0) >= 80
        elif current_difficulty == "medium":
            return accuracy_by_difficulty.get("medium", 0) >= 80
        else:
            return False  # hard级别不再进阶
    
    def _get_recommended_difficulty(
        self,
        current_difficulty: str,
        can_advance: bool,
        accuracy_by_difficulty: Dict[str, float]
    ) -> str:
        """获取推荐的难度级别"""
        if can_advance:
            if current_difficulty == "easy":
                return "medium"
            elif current_difficulty == "medium":
                return "hard"
        
        # 如果当前难度准确率太低，降级
        current_accuracy = accuracy_by_difficulty.get(current_difficulty, 0)
        if current_accuracy < 50:
            if current_difficulty == "hard":
                return "medium"
            elif current_difficulty == "medium":
                return "easy"
        
        return current_difficulty
    
    def update_user_level(self, user_id: str, question_id: str, is_correct: bool):
        """更新用户水平（记录答题结果）"""
        # 获取题目难度
        difficulty = difficulty_service.get_difficulty_level(question_id)
        
        # 更新该难度级别的统计
        if self.redis:
            try:
                level_key = f"user_level:{user_id}:{difficulty}"
                self.redis.hincrby(level_key, "total", 1)
                if is_correct:
                    self.redis.hincrby(level_key, "correct", 1)
                self.redis.expire(level_key, 86400 * 365)  # 保存1年
            except Exception as e:
                print(f"更新用户水平失败: {e}")
        
        # 同时更新内存存储
        if not hasattr(self, '_memory_storage'):
            self._memory_storage = {}
        level_key = f"user_level:{user_id}:{difficulty}"
        if level_key not in self._memory_storage:
            self._memory_storage[level_key] = {"total": 0, "correct": 0}
        self._memory_storage[level_key]["total"] += 1
        if is_correct:
            self._memory_storage[level_key]["correct"] += 1


# 单例实例
user_level_service = UserLevelService()


